﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;

namespace THO7AlgoritmTimerApplication
{
    public partial class MainForm : Form
    {
        List<VisionAlgorithm> AlgorithmList = new List<VisionAlgorithm>();
        Stopwatch stopWatch;
        int mask = 0;

        Bitmap InputImage;
        public MainForm()
        {
            InitializeComponent();

            AlgorithmList.Add(new MedianAlgorithmVar("Median 3x3b"));
            AlgorithmList.Add(new MedianAlgorithmVar("Median 11x11b"));
            AlgorithmList.Add(new MedianAlgorithm2("Variabele Median(Kleur)"));
            AlgorithmList.Add(new MedianAlgorithmVar("Variabele Median(Grijs)"));
            AlgorithmList.Add(new To16colors("16 kleuren"));
            AlgorithmList.Add(new yellow_filter("Geel filter"));
            AlgorithmList.Add(new contrast_add("contrast add"));
            AlgorithmList.Add(new Remove_black("verwijder zwart"));
            AlgorithmList.Add(new Rotate90("draai 90g"));
            AlgorithmList.Add(new Find_numberplate("zoek nummerbord"));
            AlgorithmList.Add(new range("Range filter"));
            AlgorithmList.Add(new brightness("brightness add"));
            AlgorithmList.Add(new Remove_filter("remove troep"));
            AlgorithmList.Add(new Cropwhite("knip wit"));
            AlgorithmList.Add(new test("t"));
            AlgorithmList.Add(new find_pixel("fp"));
            AlgorithmList.Add(new MaxFilter("max","Max"));
            AlgorithmList.Add(new MaxFilter("min", "Min"));
            //Insert new Algorithms here
            /*          ^
            *          /|\
            *           |
            */
            foreach (VisionAlgorithm vA in AlgorithmList)
            {
                algoRithmComboBox.Items.Add(vA.Name);
            }
        }

        private void loadButton_Click(object sender, EventArgs e)
        {
            openImage();
        }

        private void openImage()
        {
            OpenFileDialog oFD = new OpenFileDialog();
            // DIT IS VERVELEND:
            //oFD.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
            oFD.Filter = "Image Files(*.BMP;*.JPG;*.JPEG;*.PNG;)|*.BMP;*.JPG;*.JPEG;*.PNG;";
            oFD.FilterIndex = 1;
            oFD.RestoreDirectory = true;
            if (oFD.ShowDialog() == DialogResult.OK)
            {
                String CurrentFileName = Path.GetFullPath(oFD.FileName);
                InputImage = new Bitmap(CurrentFileName);
                InputPictureBox.Image = InputImage;
            }
        }



        private void AlgoButton_Click(object sender, EventArgs e)
        {

            if (InputImage != null)
            {
                InfoLabel.Text = "Start running " + AlgorithmList.ElementAt(algoRithmComboBox.SelectedIndex).Name + "...\n" + InfoLabel.Text;
                startAlgThread();
            }

        }
        private void TempPictureBox_DoubleClick(object sender, EventArgs e)
        {
            if (TempPictureBox.Image != null)
            {
                Form ipForm = new ImagePreviewForm(new Bitmap(TempPictureBox.Image));
                ipForm.Show();
            }
        }
        private void OutputPictureBox_DoubleClick(object sender, EventArgs e)
        {
            if (OutputPictureBox.Image != null) {
                Form ipForm = new ImagePreviewForm(new Bitmap(OutputPictureBox.Image));
                ipForm.Show();
            }
        }
        private void InputPictureBox_DoubleClick(object sender, EventArgs e)
        {
            if (InputPictureBox.Image != null)
            {
                Form ipForm = new ImagePreviewForm(new Bitmap(InputPictureBox.Image));
                ipForm.Show();
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void OutputToInputButton_Click(object sender, EventArgs e)
        {
            if (OutputPictureBox.Image != null)
            {
                InputImage = new Bitmap(OutputPictureBox.Image);
                InputPictureBox.Image = InputImage;
                OutputPictureBox.Image = null;
            }
        }

        private void ClearButton_Click(object sender, EventArgs e)
        {
            InfoLabel.Text = "";
            Segmentation S = new Segmentation();
            S.regonize(InputImage);
        }

        private void backgroundAlgorithmWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                MessageBox.Show("Error: " + e.Error.Message);
            }
            else if (e.Cancelled)
            {
                MessageBox.Show("Algorithm canceled.");
            }
            else
            {
                stopWatch.Stop();
                long elapsedms = stopWatch.ElapsedMilliseconds;
                int value = algoRithmComboBox.SelectedIndex;
                InfoLabel.Text = AlgorithmList.ElementAt(value).Name + " took: " + elapsedms + " ms\n" + InfoLabel.Text;
                EnableAllInputs(true);
            }
        }

        private void backgroundAlgorithmWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            System.ComponentModel.BackgroundWorker worker;
            worker = (System.ComponentModel.BackgroundWorker)sender;
            List<object> argList = (List<object>)e.Argument;
            VisionAlgorithm visAlg = (VisionAlgorithm) argList.ElementAt(0);
            visAlg.setMarge(mask);
            Bitmap InputImage = (Bitmap)argList.ElementAt(1);
            PictureBox OutputPictureBox = (PictureBox)argList.ElementAt(2);
            OutputPictureBox.Image = visAlg.DoAlgorithm(InputImage);
        }

        private void EnableAllInputs(bool state)
        {
            //openPictureToolStripMenuItem.Enabled = state;
            AlgoButton.Enabled = state;
            algoRithmComboBox.Enabled = state;
            OutputToInput.Enabled = state;
            InputPictureBox.Enabled = state;
        }

        private void startAlgThread()
        {
            List<object> argList = new List<object>();
            try {
                mask = Convert.ToInt32(inputmask1.Text);
            } catch (Exception ex) {
                mask = 0;
                inputmask1.Text = mask + "";
            }
            argList.Add(AlgorithmList.ElementAt(algoRithmComboBox.SelectedIndex));
            argList.Add(InputImage);
            argList.Add(OutputPictureBox);
            stopWatch = new Stopwatch();
            EnableAllInputs(false);
            stopWatch.Start();
            backgroundAlgorithmWorker.RunWorkerAsync(argList); 
        }

        private void saveButton_Click(object sender, EventArgs e)
        {
            if (OutputPictureBox.Image != null)
            {
                SaveFileDialog sFD = new SaveFileDialog();
                //sFD.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
                sFD.Filter = "Image Files(*.BMP;*.JPG;*.JPEG;*.PNG;)|*.BMP;*.JPG;*.JPEG;*.PNG;";
                sFD.FilterIndex = 1;
                sFD.RestoreDirectory = true;
                sFD.Title = "Save an Image File";
                if (sFD.ShowDialog() == DialogResult.OK)
                {
                    OutputPictureBox.Image.Save(sFD.FileName, System.Drawing.Imaging.ImageFormat.Jpeg);
                }
            }
        }

        private void outputToTemp_Click(object sender, EventArgs e)
        {
            if (OutputPictureBox.Image != null)
            {
                TempPictureBox.Image = OutputPictureBox.Image;
                OutputPictureBox.Image = null;
            }
        }

        private void tempToInput_Click(object sender, EventArgs e)
        {
            if (TempPictureBox.Image != null)
            {
                InputImage = new Bitmap(TempPictureBox.Image);
                InputPictureBox.Image = InputImage;
                OutputPictureBox.Image = null;
            }
        }

        private void OCRstart(object sender, EventArgs e)
        {
            OCR ocr = new OCR();
            double[] goed = ocr.learn(InputImage, inputmask1.Text);
            InfoLabel.Text = "";
            char[] volgorde = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
            for (int i = 0; i < goed.Length; i++)
            {
                InfoLabel.Text += "" + volgorde[i] + " " + goed[i] + "%\n";
            }
        }

        private void regonize(object sender, EventArgs e)
        {
            OCR ocr = new OCR();
            double[] goed = ocr.regonize(InputImage);
            InfoLabel.Text = "";
            char[] volgorde = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
            for (int i = 0; i < goed.Length; i++)
            {
                InfoLabel.Text += "" + volgorde[i] + " " + goed[i] + "%\n";
            }
        }

        private void OCR3(object sender, EventArgs e) {
            OCRnew ocr1 = new OCRnew();
            int aantal = 4;
            letter[] links = new letter[aantal];
            letter[] boven = new letter[aantal];
            int[] kans = new int[aantal];
            letter waarschijnlijk;
            Bitmap temp = new Bitmap(InputImage);
            ocr1.learn(temp, inputmask1.Text, out links, "OCRlinks.txt", "links", aantal);
            temp.RotateFlip(RotateFlipType.Rotate90FlipNone);
            ocr1.learn(temp, inputmask1.Text, out boven, "OCRboven.txt", "boven", aantal);
            for (int i = 0; i < links.Length; i++) {
                kans[i] = 0;
                for (int j = 0; j < boven.Length; j++) {
                    if (links[i].get_letter().Equals(boven[j].get_letter())) {
                        kans[i] += (links[i].get_waarde() + boven[j].get_waarde());
                    }
                }
            }
            int w = 0;
            if (kans.Max() != 0) {
                for (int i = 0; i < kans.Length; i++) {
                    if (kans[w] < kans[i]) {
                        w = i;
                    }
                }
                waarschijnlijk = links[w];
            } else {
                for (int i = 0; i < boven.Length; i++) {
                    if (boven[w].get_waarde() < boven[i].get_waarde()) {
                        w = i;
                    }
                }
                waarschijnlijk = boven[w];
            }
            Write_to_infolabel(InfoLabel, "vanaf Links", links, true);
            Write_to_infolabel(InfoLabel, "vanaf Boven", boven, false);
            Write_to_infolabel(InfoLabel, "De waarschijnlijkste", waarschijnlijk, false);
        }

        private void Recognize3(object sender, EventArgs e) {
            OCRnew ocr1 = new OCRnew();
            int aantal = 4;
            letter[] links = new letter[aantal];
            letter[] boven = new letter[aantal];
            int[] kans = new int[aantal];
            letter waarschijnlijk;
            Bitmap temp = new Bitmap(InputImage);
            links = ocr1.regonize(temp, "OCRlinks.txt", "links", aantal);
            temp.RotateFlip(RotateFlipType.Rotate90FlipNone);
            boven = ocr1.regonize(temp, "OCRboven.txt", "boven", aantal);
            for (int i = 0; i < links.Length; i++) {
                kans[i] = 0;
                for (int j = 0; j < boven.Length; j++) {
                    if (links[i].get_letter().Equals(boven[j].get_letter())) {
                        kans[i] += (links[i].get_waarde() + boven[j].get_waarde());
                    }
                }
            }
            int w = 0;
            if (kans.Max() != 0) {
                for (int i = 0; i < kans.Length; i++) {
                    if (kans[w] < kans[i]) {
                        w = i;
                    }
                }
                waarschijnlijk = links[w];
            } else {
                for (int i = 0; i < boven.Length; i++) {
                    if (boven[w].get_waarde() < boven[i].get_waarde()) {
                        w = i;
                    }
                }
                waarschijnlijk = boven[w];
            }
            Write_to_infolabel(InfoLabel, "vanaf Links", links, true);
            Write_to_infolabel(InfoLabel, "vanaf Boven", boven, false);
            Write_to_infolabel(InfoLabel, "De waarschijnlijkste", waarschijnlijk, false);
        }

        public void Save_as_CSV(String file, letter[] l) {
            StreamWriter s = new StreamWriter(file, true);
            for (int i = 0; i < l.Length; i++) {
                s.WriteLine(l[i].get_letter() + ";" + l[i].get_waarde());
            }
            s.Close();
        }
        public void Write_to_infolabel(Label text, String t, letter[] l, bool overwrite) {
            if (overwrite) {
                text.Text = t + " : \n";
            } else {
                text.Text += t + " : \n";
            }
            if (l != null) {
                for (int i = 0; i < l.Length; i++) {
                    text.Text += l[i].get_letter() + " : " + l[i].get_waarde() + "\n";
                }
            }
        }
        public void Write_to_infolabel(Label text, String t, letter l, bool overwrite) {
            if (overwrite) {
                text.Text = t + " : \n";
            } else {
                text.Text += t + " : \n";
            }
            text.Text += l.get_letter() + "\n";
        }

        private void MainForm_Load(object sender, EventArgs e)
        {

        }
    }
}
